package xueqiu

import (
	"context"
	"fmt"
	"net/http"
	"strings"
	"time"

	"gitee.com/lyuanbo/stock-trade/internal/pkg/mathx"
	"gitee.com/lyuanbo/stock-trade/internal/pkg/stock/constant"
	"github.com/imroc/req/v3"
	"github.com/pkg/errors"
)

func (x *XueQiu) Tick(codes []constant.Stock) (map[string]constant.Kline, error) {
	return nil, nil
}

// Kline 实时获取K线数据
// period: 1m, 5m, 15m, 30m, 60m, 120m, day, week, month, year
func (x *XueQiu) Kline(ctx context.Context, period string, codeIds []string) (map[string][]*constant.Kline, error) {
	m := make(map[string][]*constant.Kline)
	for _, codeId := range codeIds {
		//https://stock.xueqiu.com/v5/stock/chart/kline.json?symbol=SZ000063&begin=1718364776276&period=120m&type=before&count=-284&indicator=kline,pe,pb,ps,pcf,market_capital,agt,ggt,balance

		// 随机数字
		body, err := req.DefaultClient().R().SetContext(ctx).
			SetCookies(&http.Cookie{Name: "xq_a_token", Value: x.token}, &http.Cookie{Name: "u", Value: generateCookieU()}).
			SetQueryParams(map[string]string{
				"symbol":    codeId,
				"type":      "before",
				"count":     "-500",
				"period":    period,
				"indicator": "kline",
				"begin":     fmt.Sprintf("%d", time.Now().UnixMilli()),
			}).Get("https://stock.xueqiu.com/v5/stock/chart/kline.json")
		if err != nil {
			return nil, errors.WithMessage(err, "请求 v5/stock/chart/kline.json")
		}

		var resp klineResponse
		err = body.UnmarshalJson(&resp)
		if err != nil {
			return nil, errors.WithMessage(err, "解析 v5/stock/chart/kline.json")
		}

		if len(resp.Data.Item) == 0 {
			continue
		}

		for i, item := range resp.Data.Item {
			if _, ok := x.StockMap[resp.Data.Symbol]; !ok {
				x.StockMap[resp.Data.Symbol], _ = x.Info(ctx, resp.Data.Symbol)
			}

			kline := &constant.Kline{
				Stock:        *x.StockMap[resp.Data.Symbol],
				Date:         time.UnixMilli(int64(item[0])),
				Volume:       item[1],
				Open:         item[2],
				High:         item[3],
				Low:          item[4],
				Close:        item[5],
				Chg:          item[6],
				Percent:      item[7],
				TurnoverRate: item[8],
				Amount:       item[9],
			}
			// 有上一条，则计算咋收盘价
			if i > 0 {
				kline.LastClose = m[resp.Data.Symbol][i-1].Close
			}

			m[resp.Data.Symbol] = append(m[resp.Data.Symbol], kline)
		}
	}

	return m, nil
}

// Realtime 实时获取股票数据
// https://stock.xueqiu.com/v5/stock/realtime/quotec.json?symbol=SZ000100,SH510300
func (x *XueQiu) Realtime(ctx context.Context, codeIds []string) (map[string]*constant.Kline, error) {
	// 这个接口不需要 token，直接请求即可
	body, err := req.DefaultClient().R().SetContext(ctx).SetQueryParam("symbol", strings.Join(codeIds, ",")).Get("https://stock.xueqiu.com/v5/stock/realtime/quotec.json")
	if err != nil {
		return nil, errors.WithMessage(err, "请求 v5/stock/realtime/quotec.json")
	}

	var resp realtimeResponse
	err = body.UnmarshalJson(&resp)
	if err != nil {
		return nil, errors.WithMessage(err, "解析 v5/stock/realtime/quotec.json")
	}

	if len(resp.Data) == 0 {
		return nil, nil
	}

	m := make(map[string]*constant.Kline, len(resp.Data))
	for _, item := range resp.Data {
		stock, ok := x.StockMap[item.Symbol]
		if !ok {
			x.StockMap[item.Symbol], _ = x.Info(ctx, item.Symbol)
			stock = x.StockMap[item.Symbol]
		}
		m[item.Symbol] = &constant.Kline{
			Stock:        *stock,
			Date:         time.UnixMilli(item.Timestamp),
			Volume:       item.Volume,
			Open:         item.Open,
			High:         item.High,
			Low:          item.Low,
			Close:        item.Current,
			Chg:          item.Chg,
			Percent:      item.Percent,
			TurnoverRate: item.TurnoverRate,
			Amount:       item.Amount,
		}
	}

	return m, nil
}

// Info 获取股票详情
// https://stock.xueqiu.com/v5/stock/quote.json?symbol=SH601127&extend=detail
func (x *XueQiu) Info(ctx context.Context, codeId string) (*constant.Stock, error) {
	body, err := req.DefaultClient().R().SetContext(ctx).SetQueryParam("symbol", codeId).SetQueryParam("extend", "detail").
		SetCookies(&http.Cookie{Name: "xq_a_token", Value: x.token}).Get("https://stock.xueqiu.com/v5/stock/quote.json")
	if err != nil {
		return nil, errors.WithMessage(err, "获取 v5/stock/quote.json 接口数据")
	}

	var resp stockQuoteResponse
	err = body.UnmarshalJson(&resp)
	if err != nil {
		return nil, errors.WithMessage(err, "解析 v5/stock/quote.json 返回值")
	}

	if resp.ErrorCode != float64(0) {
		return nil, errors.Errorf("请求 v5/stock/quote.json, %s", resp.ErrorDescription)
	}

	stock := &constant.Stock{
		Code:      resp.Data.Quote.Code,
		Name:      resp.Data.Quote.Name,
		Exchange:  constant.ExchangeType(resp.Data.Quote.Exchange),
		Type:      x.listByType(resp.Data.Quote.Type),
		Precision: mathx.GetFractionLength(resp.Data.Quote.TickSize),
	}

	return stock, nil
}
